package com.dosimple.comparedatabase.controller;

import com.dosimple.comparedatabase.common.CommonResult;
import com.dosimple.comparedatabase.dto.*;
import com.dosimple.comparedatabase.exception.DefinedException;
import com.dosimple.comparedatabase.util.DBUtils;
import com.dosimple.comparedatabase.util.GsonUtils;
import com.dosimple.comparedatabase.util.QueryUtils;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cglib.core.CollectionUtils;
import org.springframework.cglib.core.Transformer;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Random;

/**
 * @auther: baolw
 * @date: 2018/6/19 0019 下午 4:13
 */
@RestController
@Slf4j
public class DBCompareController {

    @PostMapping("/initDB")
    public CommonResult<List<String>> initDB(@RequestBody InitCompareDto dto) {
        if (StringUtils.isBlank(dto.getAliasName())) {
            String name = "database-" + (DBUtils.dbs.size() + 1);
            if (DBUtils.dbs.containsKey(name)) {
                name = "database-" + ((new Random().nextInt(900)) + 100);
            }
            dto.setAliasName(name);
        } else if (DBUtils.aliasDbName.containsKey(dto.getAliasName())) {
            return new CommonResult<>(500, "已含有该别名");
        }
        String baseId = DBUtils.createCompareConnection(dto.getSourceUrl(), dto.getSourceUser(), dto.getSourcePassword()
                , dto.getTargetUrl(), dto.getTargetUser(), dto.getTargetPassword(), dto.getAliasName());
        log.info(baseId);
        System.out.println(baseId);
        try {
            List<String> source = QueryUtils.queryDBs(baseId, DBUtils.SOURCE, "show databases").getData();
            List<String> target = QueryUtils.queryDBs(baseId, DBUtils.TARGET, "show databases").getData();
            target.removeAll(source);
            return new CommonResult<>(200, target);
        } catch (DefinedException e) {
            e.printStackTrace();
            return new CommonResult<>(500, e.getMessage());
        }
    }

    @GetMapping("/dbInfo")
    public CommonResult<List<DatabasesDto>> dbInfo(@RequestParam("id") String id, @RequestParam("type") String type) {
        try {
            List<DatabasesDto> result = Lists.newArrayList();
            List<String> source = QueryUtils.queryDBs(id, DBUtils.SOURCE, "show databases").getData();
            List<String> target = QueryUtils.queryDBs(id, DBUtils.TARGET, "show databases").getData();

            List<String> sourceDiff = CollectionUtils.transform(source, new Transformer() {
                @Override
                public Object transform(Object o) {
                    return o;
                }
            });
            sourceDiff.removeAll(target);

            List<String> targetDiff = CollectionUtils.transform(target, new Transformer() {
                @Override
                public Object transform(Object o) {
                    return o;
                }
            });
            targetDiff.removeAll(source);

            if (DBUtils.SOURCE.equals(type)) {
                transDbInfo(result, source, sourceDiff);
            } else {
                transDbInfo(result, target, targetDiff);
            }

            return new CommonResult<>(200, result);
        } catch (DefinedException e) {
            e.printStackTrace();
            return new CommonResult<>(500, e.getMessage());
        }
    }

    @GetMapping("/dbTableInfo")
    public CommonResult<List<DatabasesDto>> dbTableInfo(@RequestParam("baseId") String baseId, @RequestParam("sourceName") String sourceName
            ,@RequestParam("targetName") String targetName, @RequestParam("type") String type) {
        List<DatabasesDto> result = Lists.newArrayList();
        List<String> source = QueryUtils.queryTables(baseId, DBUtils.SOURCE, sourceName).getData();
        List<String> target = QueryUtils.queryTables(baseId, DBUtils.TARGET, targetName).getData();

        List<String> interection = CollectionUtils.transform(source, new Transformer() {
            @Override
            public Object transform(Object o) {
                return o;
            }
        });
        interection.retainAll(target);
        List<TableDto> sourceTables = QueryUtils.queryTableInfo(interection, sourceName, DBUtils.SOURCE, baseId).getData();
        List<TableDto> targetTables = QueryUtils.queryTableInfo(interection, targetName, DBUtils.TARGET, baseId).getData();
        List<String> diff = Lists.newArrayList();
        for (TableDto sourceDto: sourceTables) {
            for (TableDto targetDto: targetTables) {
                if (sourceDto.getTableName().equals(targetDto.getTableName())) {
                    if (!sourceDto.equals(targetDto)) {
                        diff.add(sourceDto.getTableName());
                    }
                    break;
                }
            }
        }

        List<String> sourceDiff = CollectionUtils.transform(source, new Transformer() {
            @Override
            public Object transform(Object o) {
                return o;
            }
        });
        sourceDiff.removeAll(target);
        List<String> targetDiff = CollectionUtils.transform(target, new Transformer() {
            @Override
            public Object transform(Object o) {
                return o;
            }
        });
        targetDiff.removeAll(source);

        if (DBUtils.SOURCE.equals(type)) {
            transDbInfo(result, source, sourceDiff);
        } else {
            transDbInfo(result, target, targetDiff);
        }
        for (String table: diff) {
            for (DatabasesDto databasesDto: result) {
                if (table.equals(databasesDto.getName())) {
                    databasesDto.setColor("yellow");
                }
            }
        }
        return new CommonResult<>(200, result);
    }

    @GetMapping("/dbTableColumnInfo")
    public CommonResult<List<DatabasesDto>> dbTableColumnsInfo(@RequestParam("baseId") String baseId, @RequestParam("sourceName") String sourceName
            ,@RequestParam("targetName") String targetName, @RequestParam("type") String type
            ,@RequestParam("sourceTableName") String sourceTableName, @RequestParam("targetTableName") String targetTableName) {
        return new CommonResult<>();
    }

    private void transDbInfo(List<DatabasesDto> result, List<String> source, List<String> sourceDiff) {
        for (String str : source) {
            DatabasesDto dto = new DatabasesDto(str);
            if (sourceDiff.contains(str)) {
                dto.setColor("red");
            }
            result.add(dto);
        }
    }
}

